#include "mpLocaleUtils.h"

#ifdef PLATFORM_WINDOWS
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif //PLATFORM_WINDOWS

#include <boost/locale.hpp>
#include <boost/lexical_cast.hpp>


namespace MP{
namespace LocaleUtils{

////private member
//namespace{
//} //private member

#ifdef PLATFORM_WINDOWS


//将UFT8编码的字符串 转换成 系统默认编码的字符串（例如中文windows系统中将转换成GBK编码）
std::string u8string_to_sys_encoding(const std::string& str){
    return u8string_to_sys_encoding(str.c_str());
}

std::string u8string_to_sys_encoding(char const *text){
    static std::string codepage;
    if (codepage.empty()) {
        // 获得系统当前的代码页。对于中文Windows,
        CPINFOEX  cpinfo;
        GetCPInfoEx( CP_ACP, 0, &cpinfo );
        //cpinfo.CodePageName;
        codepage = "CP" + boost::lexical_cast<std::string>(cpinfo.CodePage);
    }

    return boost::locale::conv::between(text, codepage.c_str(), "UTF-8");
    //return boost::locale::conv::between(str, "GBK", "UTF-8");
}

//将系统默认编码的字符串 转换成 UFT8编码的字符串
std::string sys_encoding_to_u8string(const std::string& str){
    return sys_encoding_to_u8string(str.c_str());
}
std::string sys_encoding_to_u8string(char const *text){
    static std::string codepage;
    if (codepage.empty()) {
        // 获得系统当前的代码页。对于中文Windows,
        CPINFOEX  cpinfo;
        GetCPInfoEx(CP_ACP, 0, &cpinfo );
        //cpinfo.CodePageName;
        codepage = "CP" + boost::lexical_cast<std::string>(cpinfo.CodePage);
    }
    return boost::locale::conv::between(text, "UTF-8", codepage.c_str());
    //return boost::locale::conv::between(str, "UTF-8", "GBK");
}

//当前系统编码格式的字符串（例如中文windows的 GBK） 转 unicode (utf8宽字符串)
std::wstring sys_encoding_to_unicode(const std::string& str){
    return sys_encoding_to_unicode(str.c_str());
}

std::wstring sys_encoding_to_unicode(char const *text){
    static std::string codepage;
    if (codepage.empty()) {
        // 获得系统当前的代码页。对于中文Windows,
        CPINFOEX  cpinfo;
        GetCPInfoEx( CP_ACP, 0, &cpinfo );
        //cpinfo.CodePageName;
        codepage = "CP" + boost::lexical_cast<std::string>(cpinfo.CodePage);
    }
    return boost::locale::conv::to_utf<wchar_t>(text, codepage.c_str());
    //return boost::locale::conv::to_utf<wchar_t>(str, "GBK");
}


//unicode (utf8宽字符串) 转 当前系统编码格式的字符串（例如中文windows的 GBK）
std::string unicode_to_sys_encoding(const std::wstring& wstr){
    return unicode_to_sys_encoding(wstr.c_str());
}
std::string unicode_to_sys_encoding(wchar_t const *text){
    static std::string codepage;
    if (codepage.empty()) {
        // 获得系统当前的代码页。对于中文Windows,
        CPINFOEX  cpinfo;
        GetCPInfoEx( CP_ACP, 0, &cpinfo );
        //cpinfo.CodePageName;
        codepage = "CP" + boost::lexical_cast<std::string>(cpinfo.CodePage);
    }
    return boost::locale::conv::from_utf(text, codepage.c_str());
    //return boost::locale::conv::from_utf(wstr, "GBK");
}

#endif //PLATFORM_WINDOWS

//utf8宽字符(Unicode) 转 utf8窄字符串
std::string unicode_to_u8string(const std::wstring& wstr){
    return unicode_to_u8string(wstr.c_str());
}
std::string unicode_to_u8string(wchar_t const *text){
    return boost::locale::conv::from_utf(text, "UTF-8");
}

//utf8窄字符串 转 utf8宽字符(Unicode)
std::wstring u8string_to_unicode(const std::string& str){
    return u8string_to_unicode(str.c_str());
}

std::wstring u8string_to_unicode(char const *text){
    return boost::locale::conv::utf_to_utf<wchar_t>(text);
}

//检查字符串是否采用的UTF8编码
bool check_is_utf8(const std::string& str)
{
    int c,i,ix,n,j;
    for (i=0, ix=str.length(); i < ix; i++)
    {
        c = (unsigned char) str[i];
        //if (c==0x09 || c==0x0a || c==0x0d || (0x20 <= c && c <= 0x7e) ) n = 0; // is_printable_ascii
        if (0x00 <= c && c <= 0x7f) n=0; // 0bbbbbbb
        else if ((c & 0xE0) == 0xC0) n=1; // 110bbbbb
        else if ( c==0xed && i<(ix-1) && ((unsigned char)str[i+1] & 0xa0)==0xa0) return false; //U+d800 to U+dfff
        else if ((c & 0xF0) == 0xE0) n=2; // 1110bbbb
        else if ((c & 0xF8) == 0xF0) n=3; // 11110bbb
        //else if (($c & 0xFC) == 0xF8) n=4; // 111110bb //byte 5, unnecessary in 4 byte UTF-8
        //else if (($c & 0xFE) == 0xFC) n=5; // 1111110b //byte 6, unnecessary in 4 byte UTF-8
        else return false;
        for (j=0; j<n && i<ix; j++) { // n bytes matching 10bbbbbb follow ?
            if ((++i == ix) || (( (unsigned char)str[i] & 0xC0) != 0x80))
                return false;
        }
    }
    return true;
}

}   //END LocaleUtils
}   //END MP





